iT邦幫忙

2024 iThome 鐵人賽

DAY 2
0
佛心分享-刷題不只是刷題

Leecode刷題系列 第 14

D15:Q76Minimum Window Substring

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20240929/20169309MKI7z2mwJ6.png
理解題目:
這題要在字串 s 裡找到一個最小的子字串,讓這個子字串包含字串 t 裡所有的字符(包括重複的字符)。如果找不到,就返回空字串 ""。
思路:
可以用「滑動窗口」解決這類最小子串問題,滑動窗口技術的重點是擴展右邊界找到一個可行的窗口,然後收縮左邊界縮小窗口大小直到找到最小的可行解,保持一個字符頻率計數器,要維護一個字符頻率計數器來跟蹤窗口中是否已經包含了 t 裡所有的字符,這可以用兩個計數器,一個記錄 t 需要配對的字符和它們的數量,另一個記錄當前窗口裡包含的字符和數量。
步驟:
開始從字符串的左端和右端初始化一個窗口,然後右指針漸漸擴展窗口,直到找到一個包含所有 t 字符的子串,找到一個滿足條件的窗口之後,試著縮小左邊界,找到更小的可行窗口。
程式碼:
from collections import Counter

class Solution(object):
def minWindow(self, s, t):
"""
:type s: str
:type t: str
:rtype: str
"""
#邊界條件:如果 t 的長度大於 s 的長度,無法找到符合條件的子串
if len(t) > len(s):
return ""

    #算 t 中每個字符出現的次數
    t_count = Counter(t)
    current_count = {}

    #初始化滑動窗口指針
    left = 0
    min_len = float('inf')  # 把最小長度初始化無限大
    min_window = ""
    
    #要匹配的字符數
    required = len(t_count)
    formed = 0  # 記錄當前匹配的字符數

    #通過右指針擴展窗口
    for right in range(len(s)):
        char = s[right]
        current_count[char] = current_count.get(char, 0) + 1

        #如果當前字符的頻率符合 t 裡的要求
        if char in t_count and current_count[char] == t_count[char]:
            formed += 1

        #當窗口裡的字符數符合 t 的要求,試著縮小窗口
        while formed == required:
            window_len = right - left + 1
            if window_len < min_len:
                min_len = window_len
                min_window = s[left:right+1]

            #移動左指針縮小窗口
            left_char = s[left]
            current_count[left_char] -= 1
            #如果當前字符在 t 裡而且數量小於要求,就減少已配好的字符數
            if left_char in t_count and current_count[left_char] < t_count[left_char]:
                formed -= 1

            left += 1  # 縮小窗口

    #如果找到有效的最小窗口,返回結果;不然就返回空字串
    return min_window if min_len != float('inf') else ""

解釋:
計數器:t_count:算字符串 t 裡每個字符的出現次數。
current_count:算當前窗口中每個字符的出現次數。
滑動窗口:left 和 right 就是滑動窗口的左右邊界,用來動態調整窗口大小。
滿足 t 裡所有字符要求,接下來試著把窗口縮小。
檢查:窗口裡所有需要的字符都被配到時(即 formed == required),開始縮小窗口。
最小子串更新:找到一個比之前更小的符合條件的窗口時,更新最小窗口長度和內容。
結果返回:返回最小的符合條件的子串,如果沒找到就返回空字串 。

時間複雜度:
O(m + n) , m 是字串 s 的長度,n 是字串 t 的長度。
關鍵:
用滑動窗口確保線性時間的計算,維護兩個計數器,一個跟蹤目標字符頻率,另一個跟蹤窗口內字符匹配情況。
心得:
時間其實過得很快,不知不覺就已經寫了一半了,雖然每天寫偶爾還是會覺得有點煩躁,但是每天動一下腦,習慣了就會好很多,可我真的覺得需要囤一點文,週末會比較可以安排時間,總之今天又學了新東西,對於滑動窗口的運用有比較熟悉一點,這題我也花了不少時間,所以至少比較有印象。


上一篇
D14:Q72Edit Distance
下一篇
D16:Q80Remove Duplicates from Sorted Array II
系列文
Leecode刷題28
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言